const timeoutInterval = 100;
const nodeSchedule    = require("../../library/node-schedule/schedule");
const cronPasrser     = require("../../library/cron-parser/parser");

let scheduleMap = {};
let cronMap = {};

module.exports = function(lab) {
    return {
        "checkCron": function(session, cron) {
            let interval = cronPasrser.parseExpression(cron)
            let result = []
            for (var i = 0; i < 5; i++) {
                result.push(interval.next())
            }
            return @.async.resolve(result)
        },
        "@addSchedule": function(id, date, callback) {
            if (scheduleMap[id]) {
                scheduleMap[id].cancel()
            }

            @info(`${@.format.date(new Date(date),"YYYY-MM-DD hh:mm:ss")} 时进行 : ${id}`);
            scheduleMap[id] = nodeSchedule.scheduleJob(date, callback);

            return @.async.resolve();
        },
        "@cancelSchedule": function(id, type = "schedule") {
            @info(`取消进行 : ${id}`);
            switch (type) {
                case "schedule":
                    {
                        if (scheduleMap[id]) {
                            scheduleMap[id].cancel()
                        }
                        break;
                    }
                case "cron":
                    {
                        if (cronMap[id]) {
                            cronMap[id].cancel()
                        }
                        break;
                    }
            }
            return @.async.resolve();
        },
        "@scheduleCron": function(id, cron, callback) {

            if (!@.is(callback,Function)) {
                throw @lab.errors.invalid_parameters;
            }

            if (cronMap[id]) {
                cronMap[id].cancel()
            }

            @info(`运行cron ${cron} : ${id}`);

            cronMap[id] = nodeSchedule.scheduleJob(cron, function(){

                var scheduleID = "schedule://base/" + id;

                var doHandler = function(){
                    return @.async(function(){
                        setTimeout(() => {

                            @debug("executing cron " + id);

                            process.nextTick(() => {
                                try {
                                    @.async.ensure(callback()).catch(this);
                                } catch (ex) {
                                    @error(ex);
                                    this.next();
                                }
                            });

                        }, timeoutInterval * 2);
                    });
                }

                if (lab.redis.client) {
                    lab.redis.client.lock(scheduleID, timeoutInterval,doHandler)
                } else {
                    @.lock(scheduleID, timeoutInterval, doHandler)
                }

            });
            return @.async.resolve();
        }
    }
}